﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using QuickTest.Core.Compilation;
using QuickTest.Core.ServiceInterfaces;
using QuickTest.Core.TestRunner;

namespace QuickTest.Services.Packaging
{
    public class TestPackageService : ITestPackageService
    {
        private const string TEST_PACKAGE_NAME = "QuickTestPackage";
        private const string TEST_ASSEMBLY_SEARCH_PATTERN = "*tests.dll";

        private readonly ITextRetriever textRetriever;
        private readonly ICompiler compiler;
        private readonly DirectoryUri outputDirectory;

        public TestPackageService(ITextRetriever textRetriever, ICompiler compiler, DirectoryUri outputDirectory)
        {
            this.textRetriever = textRetriever;
            this.compiler = compiler;
            this.outputDirectory = outputDirectory;
        }

        public ITestPackage CreateTestPackage(string solutionPath)
        {
            CreateCleanOutputDirectory();

            Solution solution = GetSolutionFromFile(solutionPath);

            CompileSolution(solution);

            FileInfo[] files = GetCompiledTestAssembliesFromOutputDirectory();

            if (files.Length == 0) return new TestPackage(new List<string>());

            return new TestPackage(files.Select(f => f.FullName).ToList(), TEST_PACKAGE_NAME, outputDirectory.AbsolutePath);
        }

        private Solution GetSolutionFromFile(string solutionFilePath)
        {
            var fileUri = new FileUri(solutionFilePath);
            return Solution.Create(fileUri, textRetriever);
        }

        private void CompileSolution(Solution solution)
        {
            var solutionCompiler = new CompileSolution(new CompileProject());
            solutionCompiler.Compile(solution, compiler, outputDirectory);
        }

        private void CreateCleanOutputDirectory()
        {
            if (Directory.Exists(outputDirectory.AbsolutePath))
                Directory.Delete(outputDirectory.AbsolutePath, true);

            Directory.CreateDirectory(outputDirectory.AbsolutePath);
        }

        private FileInfo[] GetCompiledTestAssembliesFromOutputDirectory()
        {
            var directoryInfo = new DirectoryInfo(outputDirectory.AbsolutePath);
            return directoryInfo.GetFiles(TEST_ASSEMBLY_SEARCH_PATTERN, SearchOption.TopDirectoryOnly);
        }
    }
}